/**
* Copyright (C) 2007 Pedro Miller Rabinovitch.
* http://www.opensource.org/licenses/mit-license.php
*
* Basically, feel free to use it however you want to.
* Please give me credit where appropriate.
*
* Pedro "Shade" Miller, gmail user: pedromr
* http://exodia.org
*
* @author Miller
*
* $Id: World.as 11 2007-12-17 23:03:04Z pedromr $
*/
package org.exodia.seeds.model {
	import org.exodia.math.Vector3D;
	import org.exodia.seeds.behaviours.IBehaviour;
	import org.exodia.seeds.model.Agent;
	
	public class World {

		private var _arrAgents:Array;
		private var _startAtAgent:int;
		
		public var width:Number, height:Number, depth:Number;
		
		public function World() {
			_arrAgents = new Array();
		}
		
		public function addAgent( agent:Agent ):void {
			_arrAgents.push( agent );
		}
		
		public function tick( deltaMS:int ) : void {
			var i:int;
			var agent:Agent;
			_startAtAgent = Math.floor( Math.random() * _arrAgents.length );
			for( i = 0; i < _arrAgents.length; i++ ) {
				agent = _arrAgents[i];
				
//trace( "thr "+agent.thrust );
				agent.moveStep( deltaMS );
			}
			for( i = 0; i < _arrAgents.length; i++ ) {
				agent = _arrAgents[i];
				updateNeighbours( agent );
			}
/***
			// CHECKING VIZINHANCA
			for( i = 0; i < _arrAgents.length; i++ ) {
				agent = _arrAgents[i];
				
				for ( var j:int = 0; j < _arrAgents.length; j++ ) {
					if ( j == i )
						continue;
						
					var other:Agent = _arrAgents[j];
					
					var ij:int = agent.neighbours.indexOf( other );
					var ji:int = other.neighbours.indexOf( agent );
					if (( ij == -1 && ji > -1 ) || (ij > -1 && ji == -1 ))
						trace( "GAAAAH " );
				}
			}
/***/
			for( i = _startAtAgent; i < _arrAgents.length; i++ ) {
				agent = _arrAgents[i];
				agent.tick( deltaMS );
			}
			for( i = 0; i < _startAtAgent; i++ ) {
				agent = _arrAgents[i];
				agent.tick( deltaMS );
			}
		}
		
		private function updateNeighbours( agent:Agent ) {
			var arr:Array = agent.neighbours;
			for each( var other:Agent in _arrAgents ) {
				if( other == agent )
					continue;
					
				var radii:Number = other.radius + agent.radius;
				var dx:Number = Math.abs( other.position.x - agent.position.x ) - radii;
				var dy:Number = Math.abs( other.position.y - agent.position.y ) - radii;
				var deltaSq:Number = dx*dx + dy*dy;
				
				var index:int = arr.indexOf( other );
				
				if( deltaSq <= agent.sensorRangeSquared && index == -1 )
					arr.push( other );
				else if( deltaSq > agent.sensorRangeSquared && index != -1 )
					arr.splice( index, 1 );
			}
		}
		
		/**
		 * Corrects delta to account for walls
		 * @param	agent
		 * @param	delta Vector3D that will be changed if the agent collides
		 * @return
		 */
		public function checkMobility( agent:Agent, delta:Vector3D ) : Boolean {
			var tx:Number = agent.position.x + delta.x;
			var ty:Number = agent.position.y + delta.y;
			var bump:Boolean = false;
			
			//correction for world centered in < 0, 0, 0 >
			tx += width / 2;
			ty += height / 2;

			if( tx < agent.radius ) {
				delta.x = agent.radius - agent.position.x;
				bump = true;
			} else if( tx > width - agent.radius ) {
				delta.x = width - agent.radius - agent.position.x;
				bump = true;
			}
			
			if( ty < agent.radius ) {
				delta.y = agent.radius - agent.position.y;
				bump = true;
			} else if( ty > height - agent.radius ) {
				delta.y = height - agent.radius - agent.position.y;
				bump = true;
			}
			
			if ( depth > 0 ) {
				var tz:Number = agent.position.z + delta.z;
				tz += depth / 2;
				if( tz < agent.radius ) {
					delta.z = agent.radius - agent.position.z;
					bump = true;
				} else if( tz > height - agent.radius ) {
					delta.z = height - agent.radius - agent.position.z;
					bump = true;
				}
			}
			
			return !bump;
		}
	}
	
}
